home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1998 January / Macworld (1998-01).dmg / Shareware World / Comms & Internet / HTML mode 2.0 etc. / htmlHomePageUtils.tcl < prev    next >
Text File  |  1997-09-22  |  54KB  |  1,480 lines

  1. ## -*-Tcl-*-
  2.  # ###################################################################
  3.  #  HTML mode - tools for editing HTML documents
  4.  # 
  5.  #  FILE: "htmlHomePageUtils.tcl"
  6.  #                                    created: 97-06-26 12.51.42 
  7.  #                                last update: 97-09-22 16.39.16 
  8.  #  Author: Johan Linde
  9.  #  E-mail: <jl@theophys.kth.se>
  10.  #     www: <http://bach.theophys.kth.se/~jl/Alpha.html>
  11.  #  
  12.  # Version: 2.0
  13.  # 
  14.  # Copyright 1996, 1997 by Johan Linde
  15.  #  
  16.  # This software may be used freely, and distributed freely, as long as the 
  17.  # receiver is not obligated in any way by receiving it.
  18.  #  
  19.  # If you make improvements to this file, please share them!
  20.  # 
  21.  # ###################################################################
  22.  ##
  23.  
  24. #===============================================================================
  25. # Checking links
  26. #===============================================================================
  27.  
  28. # Check that links are valid.
  29. proc htmlCheckWindow {} {htmlCheckLinks Window}
  30. proc htmlCheckHomePage {} {htmlCheckLinks Home}
  31. proc htmlCheckFolder {} {htmlCheckLinks Folder}
  32. proc htmlCheckFile {} {htmlCheckLinks File}
  33.  
  34. proc htmlCheckLinks {where {checking 1}} {
  35.     global HTMLmodeVars
  36.         
  37.     # Save all open window?
  38.     if {$where != "Window" && 
  39.     [htmlAllSaved "-c {Save all open windows before checking links?}"] == "cancel"} { return}
  40.     set filebase 0
  41.     if {$where == "File"} {
  42.         if {[catch {getfile "Select file to scan."} files]} {return}
  43.         # Is this a text file?
  44.         if {![htmlIsTextFile $files alertnote]} {return}
  45.         set base [htmlBASEfromPath $files]
  46.         if {$HTMLmodeVars(useBigBrother)} {htmlBigBrother "$files"; return}
  47.         set path [lindex $base 1]
  48.         set homepage [lindex $base 3]
  49.         set isinfld [lindex $base [expr 3 + [lindex $base 4] / 2]]
  50.         set base [lindex $base 0]
  51.         if {$base == "file:///"} {set filebase [string length "[file dirname $files]:"]}
  52.         set filelist [htmlOpenAfile]
  53.         puts [lindex $filelist 0] $files
  54.         close [lindex $filelist 0]
  55.         set files [lindex $filelist 1]
  56.     } elseif {$where == "Window"} {
  57.         set files [stripNameCount [lindex [winNames -f] 0]]
  58.         if {![file exists $files]} {
  59.             if {[lindex [dialog -w 200 -h 70 -t "You must save the window." 10 10 390 30  \
  60.             -b Save 20 40  85 60 \
  61.             -b Cancel 110 40 175 60] 1]} {
  62.                 error ""
  63.             }
  64.             if {![catch {saveAs "Untitled.html"}]} {
  65.                 set files [stripNameCount [lindex [winNames -f] 0]]
  66.             } else {
  67.                 error "" 
  68.             }
  69.         } else {
  70.             if {[winDirty] && [askyesno "Save window?"] == "yes"} {save}
  71.         }
  72.         set base [htmlBASEfromPath $files]
  73.         if {$checking != 2 && $HTMLmodeVars(useBigBrother)} {htmlBigBrother "$files"; return}
  74.         set path [lindex $base 1]
  75.         set homepage [lindex $base 3]
  76.         set isinfld [lindex $base [expr 3 + [lindex $base 4] / 2]]
  77.         set base [lindex $base 0]
  78.         if {$base == "file:///"} {set filebase [string length "[file dirname $files]:"]}
  79.         set filelist [htmlOpenAfile]
  80.         puts [lindex $filelist 0] $files
  81.         close [lindex $filelist 0]
  82.         set files [lindex $filelist 1]
  83.     } elseif {$where == "Folder"} {
  84.         if {[catch {htmlGetDir "Folder to scan."} folder]} {return}
  85.         set base [htmlBASEfromPath $folder]
  86.         set subFolders [expr ![string compare yes [askyesno "Check files in subfolders?"]]]
  87.         if {$subFolders && ![set subFolders [expr ![htmlContainHpFolder $folder]]] &&
  88.         [lindex [dialog -w 410 -h 135 -t "The folder '[file tail $folder]' contains a\
  89.         home page folder or an include folder, but is itself not inside one. You can't\
  90.         simultaneously check links both inside and outside home page or include folders.\
  91.         Sorry!\rBut\
  92.         you can still check this folder and skip the subfolders." 10 10 400 90\
  93.         -b Check 20 105 85 125 -b Cancel 110 105 175 125] 1]} {return}
  94.         if {$HTMLmodeVars(useBigBrother)} {htmlBigBrother "$folder:" $subFolders; return}
  95.         set path [lindex $base 1]
  96.         set homepage [lindex $base 3]
  97.         set isinfld [lindex $base [expr 3 + [lindex $base 4] / 2]]
  98.         set base [lindex $base 0]
  99.         if {$base == "file:///"} {set filebase [string length "$folder:"]}
  100.         if {$subFolders} {
  101.             set files [htmlAllHTMLfiles $folder 1]
  102.         } else {
  103.             set files [htmlGetHTMLfiles $folder 1]
  104.         }
  105.     } else {
  106.         # Check that a home page is defined.
  107.         if {![htmlIsThereAHomePage]} {return}
  108.         if {[catch {htmlWhichHomePage "check links in"} hp]} {return}
  109.         set homepage [lindex $hp 0]
  110.         set isinfld $homepage
  111.         if {$HTMLmodeVars(useBigBrother)} {htmlBigBrother "$homepage:" 1; return}
  112.         set files [htmlAllHTMLfiles $homepage 1]
  113.         set base [lindex $hp 1]
  114.         set path [lindex $hp 2]
  115.     }
  116.     return [htmlScanFiles $files $base $path $homepage $isinfld $checking $filebase]
  117. }
  118.  
  119. # Select a new file for an invalid link.
  120. proc htmlLinkToNewFile {} {
  121.     if {![string match "*Invalid URLs*" [set win [lindex [winNames] 0]]] || [lindex [posToRowCol [getPos]] 0] < 3} {return}
  122.     set str [getText [lineStart [getPos]] [expr [nextLineStart [getPos]] - 1]]
  123.     gotoMatch
  124.     regexp {Line [0-9]+:([^∞]+)} $str dum url
  125.     regsub -all {\((BASE|Invalid|anchor|case)[^\)]+\)} $url "" url
  126.     set url [string trim $url]
  127.     set str ""
  128.     regexp {[^#]*} $url str
  129.     set anchor [string trim [string range $url [string length $str] end] \"]
  130.     regsub -all {[\(\)]} $url {\\\0} url
  131.     if {[catch {search -s -f 1 -i 0 -r 1 -m 0 -l [selEnd] $url [getPos]} res]} {
  132.         alertnote "Can't find link to change on selected line."
  133.         return
  134.     }
  135.     if {[set newFile [htmlGetFile]] == ""} {return}
  136.     set newLink [lindex $newFile 0]
  137.     set wh [lindex $newFile 1]
  138.     if {$wh == "" && $anchor != "" && [htmlCheckAnchor $pathToNewFile $url]} {
  139.         append newLink $anchor
  140.     }
  141.     set f [htmlURLescape2 $newLink]
  142.     if {![regsub {([^=]+=)(\"[^\"]+\"|[^ ]+)} $url "\\1\"$f\"" url]} {set url url(\"$f\")}
  143.     replaceText [set start [lindex $res 0]] [lindex $res 1] $url
  144.     # If it's an IMG tag, replace WIDTH and HEIGHT.
  145.     if {$wh != "" && [string toupper [string range $url 0 2]] == "SRC" &&
  146.     ![catch {search -s -f 0 -i 1 -r 1 -m 0 {<IMG[ \t\r\n]+[^<>]+>} $start} res1] &&
  147.     [lindex $res1 1] > [lindex $res 1]} {
  148.         if {![catch {search -s -f 1 -i 1 -r 1 -m 0 -l [expr [lindex $res1 1] + 1] {WIDTH=\"?[0-9]*\"?} [lindex $res1 0]} res2]} {
  149.             replaceText [lindex $res2 0] [lindex $res2 1] [htmlSetCase WIDTH=\"[lindex $wh 0]\"]
  150.         }
  151.         if {![catch {search -s -f 1 -i 1 -r 1 -m 0 -l [expr [lindex $res1 1] + 1] {HEIGHT=\"?[0-9]*\"?} [lindex $res1 0]} res2]} {
  152.             replaceText [lindex $res2 0] [lindex $res2 1] [htmlSetCase HEIGHT=\"[lindex $wh 1]\"]
  153.         }
  154.     }
  155.     # Remove line with corrected link.
  156.     bringToFront $win
  157.     setWinInfo read-only 0
  158.     deleteText [lineStart [getPos]] [nextLineStart [getPos]]
  159.     select [lineStart [getPos]] [nextLineStart [getPos]]
  160.     setWinInfo dirty 0
  161.     setWinInfo read-only 1
  162. }
  163.  
  164. bind '\r' <o> htmlLinkToNewFile Brws
  165. bind enter <o> htmlLinkToNewFile Brws
  166.  
  167. proc htmlBbthReadSettings {} {
  168.     set allSettings [AEBuild -r 'Bbth' core getd ---- "obj{want:type('reco'),from:null(),form:'prop',seld:type('allS')}"]
  169.     set allSettings [string range $allSettings 17 [expr [string length $allSettings] - 2]]
  170.     return $allSettings
  171. }
  172.  
  173. proc htmlBbthRestoreSettings {settings} {
  174.     AEBuild 'Bbth' core setd "----" "obj{want:type('reco'),from:null(),form:'prop',seld:type('allS')}" "data" $settings
  175. }
  176.  
  177. proc htmlBigBrother {path {searchSubFolder 0}} {
  178.     global HTMLmodeVars
  179.     # define url mapping
  180.     set urlmap [htmlURLmap]
  181.     # launches Big Brother
  182.     if {![htmlCheckRunning Bbth] && [catch {launchBackAppl Bbth}]} {
  183.         alertnote "Could not find or launch Big Brother."
  184.         return
  185.     }
  186.     if {[set vers [htmlGetVersion Bbth]] >= 1.1} {
  187.         # Read all settings.
  188.         set allSettings [htmlBbthReadSettings]
  189.         # Change settings
  190.         if {!$HTMLmodeVars(useBBoptions)} {
  191.             AEBuild 'Bbth' core setd "----" "obj{want:type('bool'),from:null(),form:'prop',seld:type('Loly')}" "data" "bool(«0$HTMLmodeVars(ignoreRemote)»)"
  192.             AEBuild 'Bbth' core setd "----" "obj{want:type('bool'),from:null(),form:'prop',seld:type('Roly')}" "data" "bool(«0$HTMLmodeVars(ignoreLocal)»)"
  193.         }
  194.         AEBuild 'Bbth' core setd "----" "obj{want:type('bool'),from:null(),form:'prop',seld:type('Sfld')}" "data" "bool(«0$searchSubFolder»)"
  195.         AEBuild 'Bbth' core setd "----" "obj{want:type('mapG'),from:null(),form:'prop',seld:type('mapS')}" "data" "\[$urlmap\]"
  196.     } else {
  197.         alertnote "Cannot change the settings in Big Brother. You need Big Brother 1.1 or later."
  198.     }
  199.     # Sends a file or folder to be opened.
  200.     sendOpenEvent noReply 'Bbth' $path
  201.     # Restore settings
  202.     if {$vers >= 1.1} {htmlBbthRestoreSettings $allSettings}
  203.     if {$HTMLmodeVars(checkInFront)} {switchTo 'Bbth'}
  204. }
  205.  
  206.  
  207. #  Checking of remote links in a document
  208. proc htmlCheckRemoteLinks {} {
  209.     global htmlNumBbthChecking
  210.     if {[htmlGetVersion Bbth] < 1.2} {
  211.         alertnote "You need Big Brother 1.2 or later to check and fix remote links."
  212.         return
  213.     }
  214.     set urlList [htmlCheckLinks Window 2]
  215.     if {![llength $urlList]} {alertnote "No remote links to check."; return}
  216.     if {![htmlCheckRunning Bbth] && [catch {launchBackAppl Bbth}]} {
  217.         alertnote "Could not find or launch Big Brother."
  218.         return
  219.     }
  220.     set htmlBbthChkdWin [stripNameCount [lindex [winNames -f] 0]]
  221.     set sep ""
  222.     foreach url $urlList {
  223.         append theRecord "$sep{Url :“[lindex $url 1]”, Id# :“[concat $url $htmlBbthChkdWin]”}"
  224.         set sep ", "
  225.     }
  226.     # Read all settings.
  227.     set allSettings [htmlBbthReadSettings]
  228.     
  229.     # Don't ignore remote links
  230.     AEBuild 'Bbth' core setd "----" "obj{want:type('bool'),from:null(),form:'prop',seld:type('Loly')}" "data" "bool(«00»)"
  231.     # No url mappings.
  232.     AEBuild 'Bbth' core setd "----" "obj{want:type('mapG'),from:null(),form:'prop',seld:type('mapS')}" "data" "\[\]"
  233.     AEBuild 'Bbth' "Bbth" "Chck" "----" "\[$theRecord\]"
  234.     htmlBbthRestoreSettings $allSettings
  235.     incr htmlNumBbthChecking [llength $urlList]
  236. }
  237.  
  238. # Takes care of events sent from Big Brother.
  239. proc htmlBbthChkdHandler {arg} {
  240.     global tileLeft tileTop tileWidth errorHeight htmlNumBbthChecking
  241.     regexp {'Id# ':“([^”]+)”} $arg dum id
  242.     regexp {CRes:([^,]+)} $arg dum result
  243.     set win [lrange $id 2 end]
  244.     switch $result {
  245.         RSuc {set str "The remote document exists."; set color 3}
  246.         LSuc {set str "The local document exists."; set color 3}
  247.         SFld {
  248.             set color 5
  249.             regexp {SCod:([^,]+)} $arg dum code
  250.             switch $code {
  251.                 "204" {set str "The document exists but contains no data."}
  252.                 "400" {set str "The server (or the proxy) reports a bad request."}
  253.                 "401" {set str "The document seems to exist but a password is required to access it."}
  254.                 "403" {set str "The document still exists but the server refuses to deliver it."}
  255.                 "404" {set str "The remote document doesn't exist."}
  256.                 "500" {set str "The server reports an internal error while trying to serve our request."}
  257.                 "501" {set str "The server doesn't seem to support checking the existence of a link."}
  258.                 "502" {set str "A gateway reported an error."}
  259.                 "503" {set str "The server is currently unable to deliver this document. This situation might be temporary."}
  260.                 default {set str "The server answered with an unknown HTTP response code."}
  261.             }
  262.         }
  263.         SMvd {
  264.             set color 1
  265.             regexp {SCod:([^,]+)} $arg dum code
  266.             regexp {nURL:“([^”]+)”} $arg dum newURL
  267.             switch $code {
  268.                 "301" {set str "The document has moved permanently to $newURL."}
  269.                 "302" {set str "The document has moved temporarily to $newURL."}
  270.                 default {set str "The document has moved to $newURL."}
  271.             }
  272.             edit -c -w $win
  273.             set l [rowColToPos [lindex $id 0] 0]
  274.             if {![catch {search -s -f 1 -i 1 -m 0 -r 0 -l [nextLineStart $l] [lindex $id 1] [lineStart $l]} res]} {
  275.                 eval replaceText $res $newURL
  276.             }
  277.         }
  278.         sFld {
  279.             set color 5
  280.             regexp {sRsn:([^,]+)} $arg dum reason
  281.             switch $reason {
  282.                 bnAb {set str "Invalid base URL: it should be an absolute URL."}
  283.                 nTCP {set str "MacTCP or Open Transport TCP/IP is needed to check remote links."}
  284.                 locF {set str "Invalid local link."}
  285.                 Open {set str "Initializing the network services failed."}
  286.                 Bind {set str "Selecting a local port failed."}
  287.                 Rslv {set str "Resolving the host name failed."}
  288.                 Conn {set str "Establishing the connection failed."}
  289.                 Send {set str "Sending the request failed."}
  290.                 Recv {set str "Receiving the server's answer failed."}
  291.                 Disc {set str "Closing the connection failed."}
  292.                 Pars {set str "The server's response doesn't conform to the HTTP/1.0 protocol."}
  293.                 Empt {set str "The server closed the connection without answering."}
  294.                 IncT {set str "The server sent only part of the document."}
  295.                 SWDr {set str "The server said the document exists, but wasn't able to deliver it."}
  296.                 NTr/ {set str "This URL should end with a slash because it points to a directory."}
  297.                 default {set str "Checking the link failed for an unknown reason."}
  298.             }
  299.         }
  300.         Sntx {set str "URL syntax error."; set color 5}
  301.     }
  302.     if {[lsearch -exact [winNames -f] "* Remote URLs *"] < 0} {
  303.         new -n "* Remote URLs *" -g $tileLeft $tileTop $tileWidth $errorHeight
  304.         insertText "Link checking results:  (<uparrow> and <downarrow> to browse, <return> to go to line\rLinks to moved pages have been changed.\r"
  305.         htmlSetWin Brws
  306.     }
  307.     bringToFront "* Remote URLs *"
  308.     setWinInfo read-only 0
  309.     goto [maxPos]
  310.     insertText "Line [lindex $id 0]: "
  311.     insertColorEscape [getPos] $color 
  312.     insertText "$str"
  313.     insertColorEscape [getPos] 0
  314.     insertText " [lindex $id 1]\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t∞$win\r"
  315.     incr htmlNumBbthChecking -1
  316.     if {!$htmlNumBbthChecking} {insertText "Done.\r"}
  317.     htmlRedraw
  318.     setWinInfo dirty 0
  319.     setWinInfo read-only 1
  320. }
  321.  
  322. # Returns a list of all HTML and CSS files in a folder and its subfolders.
  323. proc htmlAllHTMLfiles {folder {CSS 0} {toExclude ""}} {
  324.     message "Building file list…"
  325.     set filelist [htmlOpenAfile]
  326.     set fid [lindex $filelist 0]
  327.     set files [lindex $filelist 1]
  328.     set folders [list $folder]
  329.     while {[llength $folders]} {
  330.         set newFolders ""
  331.         foreach fl $folders { 
  332.             htmlGetHTMLfiles $fl $CSS $fid $toExclude
  333.             # Get folders in this folder.
  334.             if {![catch {glob "$fl:*:"} filelist]} {
  335.                 foreach fil $filelist {
  336.                     lappend newFolders [string trimright $fil :]
  337.                 }
  338.             }
  339.         }
  340.         set folders $newFolders
  341.     }
  342.     close $fid
  343.     return $files
  344. }
  345.  
  346. # Finds all HTML files in a folder
  347. proc htmlGetHTMLfiles {folder {CSS 0} {fid ""} {toExclude ""}} {
  348.     global filepats
  349.     set pats $filepats(HTML)
  350.     if {$CSS && [info exists filepats(CSS)]} {append pats " " $filepats(CSS)}
  351.     set files ""
  352.     set cl 0
  353.     if {$fid == ""} {
  354.         set filelist [htmlOpenAfile]
  355.         set fid [lindex $filelist 0]
  356.         set files [lindex $filelist 1]
  357.         set cl 1
  358.     }
  359.     if {![catch {glob -t TEXT $folder:*} filelist]} {
  360.         foreach fil $filelist {
  361.             foreach suffix $pats {
  362.                 if {[string match $suffix $fil] && [lsearch -exact $toExclude $fil] < 0} {
  363.                     puts $fid $fil
  364.                     break
  365.                 }
  366.             }
  367.         }
  368.     }
  369.     if {$cl} {close $fid}
  370.     return $files
  371. }
  372.  
  373. # Opens a filelist file. Returns fileid and path.
  374. proc htmlOpenAfile {} {
  375.     global PREFS
  376.     if {![file exists $PREFS:HTMLtmp]} {mkdir $PREFS:HTMLtmp}
  377.     set i 0
  378.     while {[file exists $PREFS:HTMLtmp:tempfile$i]} {incr i}
  379.     set fid [open $PREFS:HTMLtmp:tempfile$i w+]
  380.     return [list $fid "$PREFS:HTMLtmp:tempfile$i"]
  381. }
  382.  
  383.  
  384.  
  385. # checking = 1 or 2: called from htmlCheckLinks
  386. # checking = 1:
  387. # Scan a list of files for HTML links and check if they point to existing files.
  388. # checking = 2:
  389. # Scan a list of files for HTML links and return the remote ones for checking with Big Brother.
  390. # checking = 0: called from htmlMoveFiles
  391. # Build a list of links which point to the files just moved.
  392. proc htmlScanFiles {files baseURL basePath homepage isInFolder checking filebase {movedFiles ""}} {
  393.     global htmlURLAttr winModes HTMLmodeVars
  394.     global tileLeft tileTop tileWidth errorHeight
  395.     global htmlCaseFolders htmlCaseFiles
  396.  
  397.     set htmlCaseFolders ""; set htmlCaseFiles ""
  398.     set chCase $HTMLmodeVars(caseSensitive)
  399.     set chAnchor $HTMLmodeVars(checkAnchors)
  400.     
  401.     # Build regular expressions with URL attrs.
  402.     set exp "<!--|\[ \\t\\n\\r\]+("
  403.     foreach attr $htmlURLAttr {
  404.         append exp "$attr|"
  405.     }
  406.     set exp [string trimright $exp |]
  407.     append exp ")"
  408.  
  409.     
  410.     set expBase "<base\[ \\t\\n\\r\]+\[^>\]*>"
  411.     set expBase2 "(href=)\"?(\[^ \\t\\n\\r\">\]+)\"?"
  412.     set exp1 "${exp}(\"\[^\">\]+\"|\[^ \\t\\n\\r>\]+)"
  413.     set exp2 {/\*|[ \t\r\n]+(url)\(\"?([^\"\)]+)\"?\)}
  414.     set toCheck ""
  415.     if {$checking != 2} {
  416.         set result [htmlOpenAfile]
  417.         set fidr [lindex $result 0]
  418.     }
  419.     set checkFail 0
  420.     
  421.     set commStart1 "<!--"
  422.     set commEnd1 "-->"
  423.     set commStart2 {/*}
  424.     set commEnd2 {\*/}
  425.     
  426.     # Open file with filelist
  427.     set fid0 [open $files]
  428.  
  429.     while {![eof $fid0]} {
  430.         gets $fid0 f
  431.         if {$f == "" || [catch {open $f} fid]} {continue}
  432.         set base $baseURL
  433.         set path $basePath
  434.         set hpPath $homepage
  435.         if {$isInFolder == ""} {
  436.             set epath $f
  437.         } else {
  438.             set epath [string range $f [expr [string length $isInFolder] + 1] end]
  439.         }
  440.         regsub -all {:} $epath {/} epath
  441.         set baseText ""
  442.         message "Looking at [file tail $f]…"
  443.         set filecont [read $fid 16384]
  444.         set limit [expr [eof $fid] ? 0 : 300]
  445.         if {[regexp {\n} $filecont]} {
  446.             set newln "\n"
  447.         } else {
  448.             set newln "\r"
  449.         }
  450.         # Look for BASE.
  451.         if {[regexp -nocase -indices $expBase $filecont thisLine]} {
  452.             set preBase [string range $filecont 0 [lindex $thisLine 0]]
  453.             set comm 0
  454.             while {[regexp -indices {<!--} $preBase bCom]} {
  455.                 set preBase [string range $preBase [expr [lindex $bCom 1] - 1] end]
  456.                 set comm 1
  457.                 if {[regexp -indices -- {-->} $preBase bCom]} {
  458.                     set preBase [string range $preBase [expr [lindex $bCom 1] - 1] end]
  459.                     set comm 0
  460.                 } else {
  461.                     break
  462.                 }
  463.             }
  464.             if {!$comm && [regexp -nocase $expBase2 [string range $filecont [lindex $thisLine 0] [lindex $thisLine 1]] href b url]} {
  465.                 if {![catch {htmlBASEpieces $url} basestr]} {
  466.                     set base [lindex $basestr 0]
  467.                     set path [lindex $basestr 1]
  468.                     set epath [lindex $basestr 2]
  469.                     set hpPath ""
  470.                     set baseText "(BASE used) "
  471.                 } else {
  472.                     set baseText "(Invalid BASE) "
  473.                 }
  474.             }
  475.         }
  476.         for {set i1 1} {$i1 < 3} {incr i1} {
  477.             set exprr [set exp$i1]
  478.             if {$i1 == 2} {
  479.                 seek $fid 0
  480.                 set filecont [read $fid 16384]
  481.                 set limit [expr [eof $fid] ? 0 : 300] 
  482.             }
  483.             set commStart [set commStart$i1]
  484.             set commEnd [set commEnd$i1]
  485.             set linenum 1
  486.             set comment 0
  487.             while {1} {
  488.                 # Find all links in every line.
  489.                 while {$comment || ([regexp -nocase -indices $exprr $filecont href b url] &&
  490.                 [expr [string length $filecont] - [lindex $href 0]] > $limit)} {
  491.                     # Comment?
  492.                     if {$comment || [string range $filecont [lindex $href 0] [lindex $href 1]] == $commStart} {
  493.                         if {$comment} {
  494.                             set href {0 0}
  495.                             set subcont $filecont
  496.                         } else {
  497.                             set subcont [string range $filecont [expr [lindex $href 1] + 1] end]
  498.                         }
  499.                         if {[regexp -indices -- $commEnd $subcont cend] &&
  500.                         [expr [string length $subcont] - [lindex $cend 0]] > $limit} {
  501.                             incr linenum [regsub -all $newln [string range $filecont 0 [expr [lindex $href 1] + [lindex $cend 1]]] {} dummy]
  502.                             set filecont [string range $filecont [expr [lindex $href 1] + [lindex $cend 1]] end]
  503.                             set comment 0
  504.                             continue
  505.                         } else {
  506.                             set comment 1
  507.                             break
  508.                         }
  509.                     }
  510.                     incr linenum [regsub -all $newln [string range $filecont 0 [lindex $url 0]] {} dummy]
  511.                     set linkTo [htmlURLunEscape [string trim [string range $filecont [lindex $url 0] [lindex $url 1]] \"]]
  512.                     set nogood 0
  513.                     if {[catch {htmlPathToFile $base $path $epath $hpPath $linkTo} linkToPath]} {
  514.                         if {$linkToPath == ""} {
  515.                             set nogood 1
  516.                         } elseif {$checking == 2 && [string range $linkToPath 0 6] == "http://"} {
  517.                             # Checking remote links
  518.                             lappend toCheck [list $linenum $linkToPath]
  519.                         }
  520.                         set linkToPath ""
  521.                     } else {
  522.                         # Anchors always point to the file itself, unless there's a BASE. 
  523.                         if {[string index $linkTo 0] == "#" && $baseText == ""} {set linkToPath [list $f $f]}
  524.                         set casePath [lindex $linkToPath 1]
  525.                         set linkToPath [lindex $linkToPath 0]
  526.                     }
  527.                     # If this is BASE HREF, ignore it.
  528.                     if {[string length $baseText] && [regexp -nocase -indices $expBase $filecont thisLine] \
  529.                     && [regexp -nocase $expBase2 [string range $filecont [lindex $thisLine 0] [lindex $thisLine 1]]]\
  530.                     && [lindex $thisLine 0] < [lindex $url 0] && [lindex $thisLine 1] > [lindex $url 1]} {
  531.                         set linkToPath ""
  532.                     }
  533.                     if {$checking == 1} {
  534.                         set anchorCheck 1
  535.                         set caseOK 1
  536.                         set fext [file exists $linkToPath]
  537.                         if {$chAnchor && $linkToPath != "" && [regexp {#} $linkTo] && $fext} {set anchorCheck [htmlCheckAnchor $linkToPath $linkTo]}
  538.                         if {$chCase && $linkToPath != "" && $fext} {set caseOK [htmlCheckLinkCase $linkToPath $casePath]}
  539.                         # Does the file exist? Ignore it if it's outside home page folder.
  540.                         # Then it point to someone else's home page.
  541.                         if {!$anchorCheck || $nogood || !$caseOK || ( $linkToPath != "" && !$fext)} {
  542.                             set bText $baseText
  543.                             if {!$anchorCheck} {append bText "(anchor missing) "}
  544.                             if {!$caseOK} {append bText "(case doesn't match) "}
  545.                             if {$homepage == ""} {
  546.                                 set line [string range $f $filebase end]
  547.                             } else {
  548.                                 set line [string range $f [expr [string length $isInFolder] + 1] end]
  549.                             }
  550.                             set l [expr 20 - [string length [file tail $f]]]
  551.                             set ln [expr 5 - [string length $linenum]]
  552.                             set href [string trim [string range $filecont [lindex $href 0] [lindex $href 1]]]
  553.                             append line "[format "%$l\s" ""] Line $linenum:[format "%$ln\s" ""]$bText$href"\
  554.                             "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t∞$f"
  555.                             puts $fidr $line
  556.                             set checkFail 1
  557.                         }
  558.                     } elseif {!$checking && [lsearch -exact $movedFiles $linkToPath] >=0 } {
  559.                         set href [string trim [string range $filecont [lindex $href 0] [lindex $href 1]]]
  560.                         puts $fidr [list $f $linenum $base $path $epath $linkToPath $href]
  561.                     }
  562.                     set filecont [string range $filecont [lindex $url 1] end]
  563.                 }
  564.                 if {![eof $fid]} {
  565.                     incr linenum [regsub -all $newln [string range $filecont 0 [expr [string length $filecont] - 301]] {} dummy]
  566.                     set filecont "[string range $filecont [expr [string length $filecont] - 300] end][read $fid 16384]"
  567.                     set limit [expr [eof $fid] ? 0 : 300] 
  568.                 } else {
  569.                     break
  570.                 }
  571.             }
  572.         }
  573.         close $fid
  574.     }
  575.     close $fid0
  576.     catch {removeFile $files}
  577.     catch {unset htmlCaseFolders htmlCaseFiles filecont}
  578.     message ""
  579.     if {$checking == 1} {
  580.         if {$checkFail} {
  581.             seek $fidr 0
  582.             new -n "* Invalid URLs *" -g $tileLeft $tileTop $tileWidth $errorHeight
  583.             insertText "Incorrect links:  (<uparrow> and <downarrow> to browse, <return> to go to file,\ropt-<return> to select a new file)\r[read $fidr]"
  584.             htmlSetWin Brws
  585.         } else {
  586.             alertnote "All links are OK."
  587.         }
  588.         close $fidr
  589.         catch {removeFile [lindex $result 1]}
  590.     } elseif {!$checking} {
  591.         return $result
  592.     } else {
  593.         return $toCheck
  594.     }
  595. }
  596.  
  597. proc htmlCheckAnchor {anchorFile url} {
  598.     regexp {[^#]*#(.*)} $url dum anchor
  599.     if {[catch {open $anchorFile r} fid]} {return 1}
  600.     set exp "<!--|<(\[Aa\]|\[mM\]\[aA\]\[pP\])\[ \t\r\n\]+\[^>\]*\[nN\]\[aA\]\[mM\]\[eE\]=\"?$anchor\"?(>|\[ \t\r\n\]+\[^>\]*>)"
  601.     set filecont [read $fid 16384]
  602.     set limit [expr [eof $fid] ? 0 : 300]
  603.     set comment 0
  604.     while {1} {
  605.         while {$comment || ([regexp -indices $exp $filecont anch] &&
  606.         [expr [string length $filecont] - [lindex $anch 0]] > $limit)} {
  607.             if {$comment || [string range $filecont [lindex $anch 0] [lindex $anch 1]] == "<!--"} {
  608.                 if {$comment} {
  609.                     set anch {0 0}
  610.                     set subcont $filecont
  611.                 } else {
  612.                     set subcont [string range $filecont [expr [lindex $anch 1] + 1] end]
  613.                 }
  614.                 if {[regexp -indices -- "-->" $subcont cend] &&
  615.                 [expr [string length $subcont] - [lindex $cend 0]] > $limit} {
  616.                     set filecont [string range $filecont [expr [lindex $anch 1] + [lindex $cend 1]] end]
  617.                     set comment 0
  618.                     continue
  619.                 } else {
  620.                     set comment 1
  621.                     break
  622.                 }
  623.             } else {
  624.                 close $fid
  625.                 return 1
  626.             }
  627.         } 
  628.         if {![eof $fid]} {
  629.             set filecont "[string range $filecont [expr [string length $filecont] - 300] end][read $fid 16384]"
  630.             set limit [expr [eof $fid] ? 0 : 300] 
  631.         } else {
  632.             break
  633.         }
  634.     }
  635.     close $fid
  636.     return 0
  637. }
  638.  
  639. # Checks that the case in a link match the case in the path to file.
  640. proc htmlCheckLinkCase {path link} {
  641.     global htmlCaseFolders htmlCaseFiles
  642.     
  643.     set path [string trimright $path :]
  644.     set link [string trimright $link :]
  645.     if {[lsearch -exact $htmlCaseFiles $path] >= 0} {return 1}
  646.     set path [split $path :]
  647.     set plen [llength $path]
  648.     set llen [llength [split $link :]]
  649.     set j [expr $plen - $llen ? $plen - $llen - 1 : 0]
  650.     for {set i $j} {$i < $plen - 1} {incr i} {
  651.         set l [lindex $path [expr $i + 1]]
  652.         set psub [join [lrange $path 0 $i] :]
  653.         if {[lsearch -exact $htmlCaseFolders $psub] < 0} {
  654.             lappend htmlCaseFolders $psub
  655.             append htmlCaseFiles " " [glob -nocomplain "$psub:*"]
  656.         }
  657.         if {[lsearch -exact $htmlCaseFiles "$psub:$l"] < 0} {return 0}
  658.     }
  659.     return 1
  660. }
  661.  
  662. #===============================================================================
  663. # Moving files
  664. #===============================================================================
  665.  
  666. # Moves files from one folder to another and update all links to the moved files
  667. # as well as all links in the moved files.
  668. proc htmlMoveFiles {} {
  669.     global HTMLmodeVars
  670.     
  671.     # Check that a home page is defined.
  672.     if {![htmlIsThereAHomePage]} {return}
  673.     
  674.     if {[htmlAllSaved "{All windows must be saved before you can moves files. Save?}"] == "no"} {return}
  675.  
  676.     # Get folder to move from.
  677.     if {[catch {htmlGetDir "Move from."} fromFolder]} {return}
  678.     set base [htmlBASEfromPath $fromFolder]
  679.     # Is this folder in a home page folder?
  680.     if {[lindex $base 0] == "file:///"} {
  681.         alertnote "'[file tail $fromFolder]' is not in a home page folder or an include folder."
  682.         return 
  683.     }
  684.     set fromPath [lindex $base 1]
  685.     set homepage [lindex $base 3]
  686.     set fromBase [lindex $base 0]
  687.     set isInInclFldr [lindex $base 4]
  688.     set inclFld [lindex $base 5]
  689.     
  690.     # Check that the corresponding include or home page folder exists.
  691.     if {$isInInclFldr} {
  692.         if {![file isdirectory $homepage]} {
  693.             alertnote "Could not find the corresponding home page folder for\
  694.             ${fromBase}$fromPath. Fix that and try again."
  695.             htmlHomePages "${fromBase}$fromPath"
  696.             return
  697.         }
  698.     } elseif {$inclFld != "" && ![file isdirectory $inclFld]} {
  699.         alertnote "Could not find the corresponding include folder for\
  700.         ${fromBase}$fromPath. Fix that and try again."
  701.         htmlHomePages "${fromBase}$fromPath"
  702.         return
  703.     }
  704.     
  705.         
  706.     # Get files to move.
  707.     set files [glob -nocomplain "$fromFolder:*"]
  708.     foreach f $files {
  709.         if {![file isdirectory $f]} {
  710.             lappend filelist [file tail $f]
  711.         }
  712.     }
  713.     if {![info exists filelist]} {
  714.         alertnote "Empty folder."
  715.         return
  716.     }
  717.     
  718.     if {[catch {listpick -p "Select files to move." -l $filelist} movefiles] || \
  719.     ![string length $movefiles]} {return}
  720.     
  721.     # Get folder to move to.
  722.     if {[catch {htmlGetDir "Move to."} toFolder]} {return}
  723.     if {$fromFolder == $toFolder} {
  724.         alertnote "This is the same folder as you moved from."
  725.         return
  726.     }
  727.     # Is this folder in the same home page folder?
  728.     if {!$isInInclFldr && ![string match "${homepage}:*" "$toFolder:"] ||
  729.     $isInInclFldr && ![string match "${inclFld}:*" "$toFolder:"]} {
  730.         set msg {"home page" "" "" "" "include"}
  731.         alertnote "'[file tail $toFolder]' is not in the same [lindex $msg $isInInclFldr] folder."
  732.         return
  733.     }
  734.     
  735.     # Move the files.
  736.     foreach f $movefiles {
  737.         if {[file exists "$toFolder:$f"]} {
  738.             if {[askyesno "Replace '$f' in folder '[file tail $toFolder]'?"] == "yes"} {
  739.                 removeFile "$toFolder:$f"
  740.             } else {
  741.                 continue
  742.             }
  743.         }
  744.         set reo 0
  745.         foreach w [winNames -f] {
  746.             if {[stripNameCount $w] == "$fromFolder:$f"} {
  747.                 alertnote "'[file tail $w]' must be closed before it can be moved. It will be reopened again."
  748.                 bringToFront $w
  749.                 killWindow
  750.                 set reo 1
  751.             }
  752.         }
  753.         if {[catch {mv "$fromFolder:$f" "$toFolder:$f"}] && ![file exists "$toFolder:$f"]} {
  754.             alertnote "Could not move $f. An error occurred."
  755.             if {$reo} {lappend reOpen "$fromFolder:$f"}
  756.         } else {
  757.             lappend movedFiles "$fromFolder:$f"
  758.             lappend movedFiles2 "$toFolder:$f"
  759.             if {$reo} {lappend reOpen "$toFolder:$f"}
  760.         }
  761.     }
  762.     
  763.     if {[info exists movedFiles] && $isInInclFldr} {
  764.         if {[lindex [dialog -w 400 -h 70 -t "Files have been moved. Update links?" \
  765.         10 10 290 30 -b Update 20 40 85 60 -b Cancel 105 40 170 60] 0]} {
  766.             set changed ""
  767.             set num [htmlUpdateAfterMove2 $movedFiles $movedFiles2 $fromBase $fromPath $inclFld]
  768.             set x [htmlUpdateAfterMove3 $movedFiles $movedFiles2 $homepage $inclFld]
  769.             incr num [lindex $x 0]
  770.             set changed [concat $changed [lindex $x 1]]
  771.         }
  772.     } elseif {[info exists movedFiles]} {
  773.         set box " -t {Files have been moved. Update links?} 10 10 390 30"
  774.         if {$inclFld != ""} {
  775.             append box " -r {Update both home page folder and include folder} 1 10 40 390 55 \
  776.             -r {Update only home page folder} 0 10 60 390 75 -r {Update only include folder} 0 10 80 390 95"
  777.             set he 140
  778.         } else {
  779.             set he 70
  780.         }
  781.         append box " -b Update 20 [expr $he - 30] 85 [expr $he - 10] -b Cancel 105 [expr $he - 30] 170 [expr $he - 10]"
  782.         set values [eval [concat dialog -w 400 -h $he $box]]
  783.         if {$inclFld != "" && ([lindex $values 0] || [lindex $values 1]) && [lindex $values 3] ||
  784.         $inclFld == "" && [lindex $values 0]} {
  785.             set x [htmlUpdateAfterMove $movedFiles $movedFiles2 $fromBase $fromPath $homepage $homepage]
  786.             set num [lindex $x 0]
  787.             set changed [lindex $x 1]
  788.             incr num [htmlUpdateAfterMove2 $movedFiles $movedFiles2 $fromBase $fromPath $homepage]
  789.         }
  790.         if {$inclFld != "" && ([lindex $values 0] || [lindex $values 2]) && [lindex $values 3]} {
  791.             set x [htmlUpdateAfterMove $movedFiles $movedFiles2 $fromBase $fromPath $homepage $inclFld]
  792.             incr num [lindex $x 0]
  793.             set changed [concat $changed [lindex $x 1]]
  794.         }    
  795.     }
  796.     
  797.     catch {message "$num files has been modified including the ones moved."}
  798.  
  799.     if {[info exists reOpen] && [askyesno "Reopen previously closed windows?"] == "yes"} {
  800.         foreach r $reOpen {
  801.             edit $r
  802.         }
  803.     }
  804.     
  805.     if {[llength $changed] && [askyesno "Update affected windows?"] == "yes"} {
  806.         foreach r $changed {
  807.             bringToFront $r
  808.             revert
  809.         }
  810.     }
  811. }
  812.  
  813. # Updates links to moved files.
  814. proc htmlUpdateAfterMove {movedFiles movedFiles2 fromBase fromPath homepage isinfld} {
  815.     global htmlURLAttr
  816.     
  817.     set allfiles [htmlAllHTMLfiles $isinfld 1 $movedFiles2]
  818.     
  819.     # Build regular expressions with URL attrs.
  820.     set exp "("
  821.     foreach attr $htmlURLAttr {
  822.         append exp "$attr|"
  823.     }
  824.     set exp [string trimright $exp |]
  825.     append exp ")"
  826.  
  827.     set exprr "${exp}(\"\[^\">\]+\"|\[^ \\t\\n\\r>\]+)"
  828.     set exprr2 {(url)\((\"?[^\"\)]+\"?)\)}
  829.  
  830.     # Update links to the moved files.
  831.     set toModify [htmlScanFiles $allfiles $fromBase $fromPath $homepage $isinfld 0 0 $movedFiles]
  832.     set fidr [lindex $toModify 0]
  833.     seek $fidr 0
  834.     set num 0
  835.     set changed ""
  836.     set thisfile ""
  837.     while {![eof $fidr]} {
  838.         gets $fidr modify
  839.         if {$modify == ""} {continue}
  840.  
  841.         set fil [lindex $modify 0]
  842.         if {$thisfile != $fil} {
  843.             if {[string length $thisfile]} {
  844.                 if {[catch {open $thisfile w} fid]} {
  845.                     alertnote "Could not update [file tail $thisfile]. An error occurred."
  846.                 } else {
  847.                     puts -nonewline $fid [join $filecont "\r"]
  848.                     close $fid
  849.                 }
  850.             }
  851.             message "Modifying [file tail $fil]…"
  852.             foreach w [winNames -f] {
  853.                 if {[stripNameCount $w] == "$fil"} {
  854.                     lappend changed $w
  855.                 }
  856.             }
  857.             set fid [open $fil r]
  858.             incr num
  859.             set filec [read $fid]
  860.             close $fid
  861.             if {[regexp {\n} $filec]} {
  862.                 set newln "\n"
  863.             } else {
  864.                 set newln "\r"
  865.             }
  866.             set filec [split $filec $newln]
  867.             set filecont ""
  868.             foreach fc $filec {
  869.                 lappend filecont [string trimleft $fc "\r"]
  870.             }
  871.         }
  872.         set thisfile $fil
  873.         set linenum [expr [lindex $modify 1] - 1]
  874.         set line [lindex $filecont $linenum]
  875.         set path [lindex $movedFiles2 [lsearch -exact $movedFiles [lindex $modify 5]]]
  876.         set lnk [htmlBASEfromPath $path]
  877.         if {[lindex $modify 2] == [lindex $lnk 0]} {
  878.             set linkTo [htmlRelativePath "[lindex $modify 3][lindex $modify 4]" "[lindex $lnk 1][lindex $lnk 2]"]
  879.         } else {
  880.             set linkTo [join [lrange $lnk 0 2] ""]
  881.         }
  882.         set linkTo [htmlURLescape2 $linkTo]
  883.         regsub -all {[\(\)]} [lindex $modify 6] {\\\0} tomod
  884.         regexp -indices $tomod $line href
  885.         if {![regexp -nocase -indices $exprr [string range $line [lindex $href 0] [lindex $href 1]] a b url]} {
  886.             regexp -nocase -indices $exprr2 [string range $line [lindex $href 0] [lindex $href 1]] a b url
  887.         }
  888.         set anchor ""
  889.         regexp {[^#]*(#[^\"]*)} $tomod a anchor
  890.         set line "[string range $line 0 [expr [lindex $href 0] + [lindex $url 0] - 1]]\"$linkTo$anchor\"[string range $line [expr [lindex $href 0] + [lindex $url 1] + 1] end]"
  891.         set filecont [lreplace $filecont $linenum $linenum $line]
  892.     }
  893.     if {$thisfile != ""} {
  894.         if {[catch {open $thisfile w} fid]} {
  895.             alertnote "Could not update [file tail $thisfile]. An error occurred."
  896.         } else {
  897.             puts -nonewline $fid [join $filecont "\r"]
  898.             close $fid
  899.         }
  900.     }
  901.     close $fidr
  902.     catch {removeFile [lindex $toModify 1]}
  903.     return [list $num $changed]
  904. }
  905.  
  906. # Updates links in moved files.
  907. proc htmlUpdateAfterMove2 {movedFiles movedFiles2 fromBase fromPath homepage} {
  908.     global htmlURLAttr
  909.     
  910.     set expBase "<(base\[ \\t\\n\\r\]+)\[^>\]*>"
  911.     set expBase2 "(href=)\"?(\[^ \\t\\n\\r\">\]+)\"?"
  912.  
  913.     # Build regular expressions with URL attrs.
  914.     set exp "("
  915.     foreach attr $htmlURLAttr {
  916.         append exp "$attr|"
  917.     }
  918.     set exp [string trimright $exp |]
  919.     append exp ")"
  920.  
  921.     
  922.     set exprr1 "<!--|\[ \\t\\n\\r\]+$exp\"?(\[^ \\t\\n\\r\">\]+)\"?"
  923.     set exprr2 {/\*|[ \t\n\r]+(url)\(\"?([^\"\)]+)\"?\)}
  924.     set commStart1 "<!--"
  925.     set commEnd1 "-->"
  926.     set commStart2 {/*}
  927.     set commEnd2 {\*/}
  928.  
  929.     set num 0
  930.     foreach f $movedFiles2 {
  931.         getFileInfo $f finfo
  932.         if {$finfo(type) != "TEXT"} {continue}
  933.         message "Modifying [file tail $f]…"
  934.         set created $finfo(created)
  935.         set fid [open $f r]
  936.         set filecont [read $fid 16384]
  937.         set limit [expr [eof $fid] ? 0 : 300]
  938.         set temp [htmlOpenAfile]
  939.         set tempf [lindex $temp 1]
  940.         set tempfid [lindex $temp 0]
  941.         set oldfile [lindex $movedFiles [lsearch -exact $movedFiles2 $f]]
  942.         set base $fromBase
  943.         set path $fromPath
  944.         set hpPath $homepage
  945.         set epath [string range $oldfile [expr [string length $homepage] + 1] end]
  946.         regsub -all {:} $epath {/} epath
  947.         # Replace newline chars in IBM files.
  948.         regsub -all "\n\r" $filecont "\r" filecont
  949.         # If BASE is used, only modify links to moved files.
  950.         set hasBase 0
  951.         if {[regexp -nocase -indices $expBase $filecont this]} {
  952.             set preBase [string range $filecont 0 [lindex $this 0]]
  953.             set comm 0
  954.             while {[regexp -indices {<!--} $preBase bCom]} {
  955.                 set preBase [string range $preBase [expr [lindex $bCom 1] - 1] end]
  956.                 set comm 1
  957.                 if {[regexp -indices -- {-->} $preBase bCom]} {
  958.                     set preBase [string range $preBase [expr [lindex $bCom 1] - 1] end]
  959.                     set comm 0
  960.                 } else {
  961.                     break
  962.                 }
  963.             }
  964.             if {!$comm && [regexp -nocase $expBase2 [string range $filecont [lindex $this 0] [lindex $this 1]] d1 d2 url1]} {
  965.                 set hasBase 1
  966.             }
  967.         }
  968.         if {$hasBase && ![catch {htmlBASEpieces $url1} basestr]} {
  969.             set base [lindex $basestr 0]
  970.             set path [lindex $basestr 1]
  971.             set epath [lindex $basestr 2]
  972.             set hpPath ""
  973.         }
  974.         incr num
  975.         for {set i1 1} {$i1 < 3} {incr i1} {
  976.             if {$i1 == 2} {
  977.                 close $fid
  978.                 seek $tempfid 0
  979.                 set fid $tempfid
  980.                 set filecont [read $fid 16384]
  981.                 set limit [expr [eof $fid] ? 0 : 300]
  982.                 set temp [htmlOpenAfile]
  983.                 set tempfid [lindex $temp 0]
  984.             }
  985.             set commStart [set commStart$i1]
  986.             set commEnd [set commEnd$i1]
  987.             set exprr [set exprr$i1]
  988.             set comment 0
  989.             while {1} {
  990.                 while {$comment || ([regexp -nocase -indices $exprr $filecont href b url] &&
  991.                 [expr [string length $filecont] - [lindex $href 0]] > $limit)} {
  992.                     # Comment?
  993.                     if {$comment || [string range $filecont [lindex $href 0] [lindex $href 1]] == $commStart} {
  994.                         if {$comment} {
  995.                             set href {0 0}
  996.                             set subcont $filecont
  997.                         } else {
  998.                             set subcont [string range $filecont [expr [lindex $href 1] + 1] end]
  999.                         }
  1000.                         if {[regexp -indices -- $commEnd $subcont cend] &&
  1001.                         [expr [string length $subcont] - [lindex $cend 0]] > $limit} {
  1002.                             puts -nonewline $tempfid [string range $filecont 0 [expr [lindex $href 1] + [lindex $cend 1] - 1]]
  1003.                             set filecont [string range $filecont [expr [lindex $href 1] + [lindex $cend 1]] end]
  1004.                             set comment 0
  1005.                             continue
  1006.                         } else {
  1007.                             set comment 1
  1008.                             break
  1009.                         }
  1010.                     }
  1011.                     
  1012.                     set urltxt [string range $filecont [lindex $url 0] [lindex $url 1]]
  1013.                     # No need to update links beginning with a /
  1014.                     if {[string index $urltxt 0] == "/"} {
  1015.                         puts -nonewline $tempfid [string range $filecont 0 [lindex $url 1]]
  1016.                         set filecont [string range $filecont [expr [lindex $url 1] + 1] end]
  1017.                         continue
  1018.                     }    
  1019.                     set anchor ""
  1020.                     regexp {[^#]*(#[^\"]*)} $urltxt a anchor
  1021.                     set urltxt [htmlURLunEscape $urltxt]
  1022.                     if {[catch {lindex [htmlPathToFile $base $path $epath $hpPath $urltxt] 0} topath]} {set topath ""}
  1023.                     # Ignore anchors if not moved and BASE.
  1024.                     # Is the link pointing to a previously moved file?
  1025.                     if {[set mvind [lsearch -exact $movedFiles $topath]] >= 0} {
  1026.                         set topath [lindex $movedFiles2 $mvind]
  1027.                         if {!$hasBase && [string index $urltxt 0] == "#"} {set topath ""}
  1028.                     } elseif {[string index $urltxt 0] == "#"} {
  1029.                         set topath ""
  1030.                     }
  1031.                         
  1032.                     if {$hasBase && [regexp -nocase -indices $expBase $filecont thisLine] \
  1033.                     && [regexp -nocase $expBase2 [string range $filecont [lindex $thisLine 0] [lindex $thisLine 1]]]\
  1034.                     && [lindex $thisLine 0] < [lindex $url 0] && [lindex $thisLine 1] > [lindex $url 1]} {
  1035.                         set topath ""
  1036.                     }
  1037.                     if {[string length $topath]} {
  1038.                         set lnk [htmlBASEfromPath $topath]
  1039.                         if {!$hasBase} {
  1040.                             set lnk1 [htmlBASEfromPath $f]
  1041.                             set path2 [lindex $lnk1 1]
  1042.                             set epath2 [lindex $lnk1 2]
  1043.                         } else {
  1044.                             set path2 $path
  1045.                             set epath2 $epath
  1046.                         }
  1047.                         if {$base == [lindex $lnk 0]} {
  1048.                             set newurl [htmlRelativePath "$path2$epath2" "[lindex $lnk 1][lindex $lnk 2]"]
  1049.                         } else {
  1050.                             set newurl [join [lrange $lnk 0 2] ""]
  1051.                         }
  1052.                         append newurl $anchor
  1053.                     } elseif {!$hasBase && ($urltxt == ".." || [string range $urltxt 0 2] == "../")} {
  1054.                         # Special case with relative links outside home page.
  1055.                         set urlspl [split $urltxt /]
  1056.                         set old [split $oldfile :]
  1057.                         set new [split $f :]
  1058.                         if {[llength $new] > [llength $old]} {
  1059.                             set newurl ""
  1060.                             for {set i 0} {$i < [expr [llength $new] - [llength $old]]} {incr i} {
  1061.                                 append newurl "../"
  1062.                             }
  1063.                             append newurl $urltxt
  1064.                         } else {
  1065.                             set ok 1
  1066.                             for {set i 0} {$i < [expr [llength $old] - [llength $new]]} {incr i} {
  1067.                                 if {[lindex $urlspl $i] != ".."} {set ok 0}
  1068.                             }
  1069.                             if {$ok} {
  1070.                                 set newurl "[join [lrange $urlspl [expr [llength $old] - [llength $new]] end] /]$anchor"
  1071.                             } else {
  1072.                                 set newurl $urltxt
  1073.                             }
  1074.                         }
  1075.                     } else {
  1076.                         set newurl $urltxt
  1077.                     }
  1078.                     puts -nonewline $tempfid [string range $filecont 0 [expr [lindex $url 0] - 1]]
  1079.                     puts -nonewline $tempfid [htmlURLescape2 $newurl]
  1080.                     set filecont [string range $filecont [expr [lindex $url 1] + 1] end]
  1081.                 }
  1082.                 if {![eof $fid]} {
  1083.                     puts -nonewline $tempfid [string range $filecont 0 [expr [string length $filecont] - 301]]
  1084.                     set filecont "[string range $filecont [expr [string length $filecont] - 300] end][read $fid 16384]"
  1085.                     set limit [expr [eof $fid] ? 0 : 300] 
  1086.                 } else {
  1087.                     break
  1088.                 }
  1089.             }
  1090.             puts -nonewline $tempfid $filecont
  1091.         }
  1092.         close $fid
  1093.         close $tempfid
  1094.         if {[catch {removeFile $f}] && [file exists $f]} {
  1095.             alertnote "Could not update [file tail $f]. An error occurred."
  1096.         } else {
  1097.             catch {copyFile [lindex $temp 1] $f; setFileInfo $f created $created}
  1098.         }
  1099.         catch {removeFile [lindex $temp 1]}
  1100.         catch {removeFile $tempf}
  1101.     }
  1102.     return $num
  1103. }
  1104.  
  1105. # Updates include links to moved files in include folder.
  1106. proc htmlUpdateAfterMove3 {movedFiles movedFiles2 homepage inclFldr} {
  1107.     set num 0
  1108.     set changed ""
  1109.     set allFiles [htmlAllHTMLfiles $homepage]
  1110.     set fid0 [open $allFiles]
  1111.  
  1112.     while {![eof $fid0]} {
  1113.         gets $fid0 fil
  1114.         if {$fil == "" || [catch {open $fil} fid]} {continue}
  1115.         set filecont [read $fid 16384]
  1116.         set limit [expr [eof $fid] ? 0 : 300]
  1117.         message "Looking at [file tail $fil]…"
  1118.         getFileInfo $fil finfo
  1119.         set created $finfo(created)
  1120.         regsub -all "\n\r" $filecont "\r" filecont
  1121.         set temp [htmlOpenAfile]
  1122.         set tmpfid [lindex $temp 0]
  1123.         set ismod 0
  1124.         while {1} {
  1125.             while {[regexp -nocase -indices {<!--[ \t\r\n]+#INCLUDE[ \t\r\n]+[^>]+>} $filecont res] &&
  1126.             [expr [string length $filecont] - [lindex $res 0]] > $limit} {
  1127.                 set link [string range $filecont [lindex $res 0] [lindex $res 1]]
  1128.                 if {[regexp -nocase -indices {FILE=\"([^\"]+)\"} $link dum res1] &&
  1129.                 [set ind [lsearch -exact $movedFiles [htmlResolveInclPath [htmlUnQuote \
  1130.                     [string range $link [lindex $res1 0] [lindex $res1 1]]] $inclFldr:]]] >= 0} {
  1131.                     puts -nonewline $tmpfid [string range $filecont 0 [expr [lindex $res 0] + [lindex $res1 0] - 1]]
  1132.                     puts -nonewline $tmpfid [htmlQuote [htmlConvertInclPath [lindex $movedFiles2 $ind] $inclFldr:]]
  1133.                     puts -nonewline $tmpfid [string range $filecont [expr [lindex $res 0] + [lindex $res1 1] + 1] [lindex $res 1]]
  1134.                     set ismod 1
  1135.                     message "Modifying [file tail $fil]…"
  1136.                 } else {
  1137.                     puts -nonewline $tmpfid [string range $filecont 0 [lindex $res 1]]
  1138.                 }
  1139.                 set filecont [string range $filecont [expr [lindex $res 1] + 1] end]
  1140.             }
  1141.             if {![eof $fid]} {
  1142.                 puts -nonewline $tmpfid [string range $filecont 0 [expr [string length $filecont] - 301]]
  1143.                 set filecont "[string range $filecont [expr [string length $filecont] - 300] end][read $fid 16384]"
  1144.                 set limit [expr [eof $fid] ? 0 : 300]
  1145.             } else {
  1146.                 break
  1147.             }
  1148.         }
  1149.         puts -nonewline $tmpfid $filecont
  1150.         close $tmpfid
  1151.         close $fid
  1152.         if {$ismod} {
  1153.             if {[catch {removeFile $fil}] && [file exists $fil]} {
  1154.                 alertnote "Could not update [file tail $fil]. An error occurred."
  1155.             } else {
  1156.                 catch {copyFile [lindex $temp 1] $fil; setFileInfo $fil created $created}
  1157.             }
  1158.             incr num
  1159.             foreach w [winNames -f] {
  1160.                 if {[stripNameCount $w] == "$fil"} {
  1161.                     lappend changed $w
  1162.                 }
  1163.             }
  1164.         }
  1165.         catch {removeFile [lindex $temp 1]}
  1166.     }
  1167.     close $fid0
  1168.     catch {removeFile $allFiles}
  1169.     return [list $num $changed]
  1170. }
  1171.  
  1172.  
  1173. #===============================================================================
  1174. # Includes
  1175. #===============================================================================
  1176. proc htmlConvertInclPath {fil path} {
  1177.     if {$path != "" && [string match "${path}*" $fil]} {
  1178.         return ":INCLUDE:[string range $fil [string length $path] end]"
  1179.     }
  1180.     return $fil
  1181. }
  1182.  
  1183. # Inserts new include tags at the current position.
  1184. proc htmlInsertIncludeTags {} {
  1185.     set sexpr {<!--[ \t\r\n]+#INCLUDE[ \t\r\n]+[^>]+>}
  1186.     set eexpr {<!--[ \t\r\n]+/#INCLUDE[ \t\r\n]+[^>]+>}
  1187.     if {![catch {search -s -f 0 -r 1 -i 1 -m 0 $sexpr [getPos]} res] &&
  1188.         ([catch {search -s -f 0 -r 1 -i 1 -m 0 $eexpr [getPos]} res1]
  1189.         || [lindex $res 0] > [lindex $res1 0])} {
  1190.         alertnote "Current position is inside an include container."
  1191.         return
  1192.     }
  1193.     if {![catch {search -s -f 1 -r 1 -i 1 -m 0 $eexpr [getPos]} res] &&
  1194.         ([catch {search -s -f 1 -r 1 -i 1 -m 0 $sexpr [getPos]} res1]
  1195.         || [lindex $res 0] < [lindex $res1 0])} {
  1196.         alertnote "Current position is inside an include container."
  1197.         return
  1198.     }
  1199.     if {[catch {getfile "Select file to include."} fil]} {return}
  1200.     if {![htmlIsTextFile $fil alertnote]} {return}
  1201.     set fil1 [htmlQuote [htmlConvertInclPath $fil \
  1202.         [htmlWhichInclFolder [stripNameCount [lindex [winNames -f] 0]]]]]
  1203.     set text "<!-- [htmlSetCase {#INCLUDE FILE=}]\"$fil1\" -->\r\r"
  1204.     if {![catch {readFile $fil} intext]} {
  1205.         regsub -all "\n\r" $intext "\r" intext
  1206.         # Remove include tags from inserted text
  1207.         regsub -all -nocase $sexpr $intext "" intext
  1208.         regsub -all -nocase $eexpr $intext "" intext
  1209.         append text $intext
  1210.     }
  1211.     append text "\r\r" "<!-- [htmlSetCase /#INCLUDE] -->"
  1212.     insertText [htmlOpenCR "" 1] $text "\r\r"
  1213. }
  1214.  
  1215. # Updates the text between all include tags.
  1216. proc htmlUpdateWindow {} {htmlUpdateInclude Window}
  1217. proc htmlUpdateHomePage {} {htmlUpdateInclude Home}
  1218. proc htmlUpdateFolder {} {htmlUpdateInclude Folder}
  1219. proc htmlUpdateFile {} {htmlUpdateInclude File}
  1220.  
  1221. proc htmlUpdateInclude {where} {
  1222.     global HTMLmodeVars winModes
  1223.     global tileLeft tileTop tileWidth errorHeight
  1224.     
  1225.     set sexpr {<!--[ \t\r\n]+#INCLUDE[ \t\r\n]+[^>]+>}
  1226.     set eexpr {<!--[ \t\r\n]+/#INCLUDE[ \t\r\n]+[^>]+>}
  1227.     if {$where == "Window"} {
  1228.         set wname [stripNameCount [lindex [winNames -f] 0]]
  1229.         set inclFldr [htmlWhichInclFolder $wname]
  1230.         set pos 0
  1231.         while {![catch {search -s -f 1 -r 1 -i 1 -m 0 $sexpr $pos} res]} {
  1232.             set lnum [lindex [posToRowCol [lindex $res 0]] 0]
  1233.             set ln [expr 5 - [string length $lnum]]
  1234.             if {[catch {search -s -f 1 -r 1 -i 1 -m 0 $eexpr [lindex $res 1]} res1]} {
  1235.                 append err "Line $lnum:[format "%$ln\s" ""]Opening include tag without a matching end tag."\
  1236.                         "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t∞$wname\r"
  1237.                 break
  1238.             }
  1239.             if {![catch {search -s -f 1 -r 1 -i 1 -m 0 $sexpr [lindex $res 1]} res2]
  1240.             && [lindex $res2 0] < [lindex $res1 0]} {
  1241.                 append err "Line $lnum:[format "%$ln\s" ""]Nested include tags."\
  1242.                         "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t∞$wname\r"
  1243.                 set pos [lindex $res1 1]
  1244.                 continue
  1245.             }    
  1246.             if {[catch {htmlReadInclude [eval getText $res] 1 $inclFldr} text]} {
  1247.                 append err "Line $lnum:[format "%$ln\s" ""]$text"\
  1248.                         "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t∞$wname\r"
  1249.                 set pos [lindex $res1 1]
  1250.             } else {
  1251.                 replaceText [lindex $res 1] [lindex $res1 0] "\r\r" $text "\r\r"
  1252.                 set pos [expr [lindex $res 1] + [string length $text] + 4]
  1253.             }
  1254.         }
  1255.     } else {
  1256.         if {[htmlAllSaved "-c {Save all open windows before updating?}"] == "cancel"} {return}
  1257.         if {$where == "File"} {
  1258.             if {[catch {getfile "Select file to update."} files]} {return}
  1259.             if {![htmlIsTextFile $files alertnote]} {return}
  1260.             set inclFldr [htmlWhichInclFolder $files]
  1261.             set folder [file dirname $files]
  1262.             set filelist [htmlOpenAfile]
  1263.             puts [lindex $filelist 0] $files
  1264.             close [lindex $filelist 0]
  1265.             set files [lindex $filelist 1]
  1266.         } elseif {$where == "Folder"} {
  1267.             if {[catch {htmlGetDir "Update folder:"} folder]} {return}
  1268.             set inclFldr [htmlWhichInclFolder "${folder}:"]
  1269.             set subFolders [expr ![string compare yes [askyesno "Update files in subfolders?"]]]
  1270.             if {$subFolders} {
  1271.                 set files [htmlAllHTMLfiles $folder]
  1272.             } else {
  1273.                 set files [htmlGetHTMLfiles $folder]
  1274.             }
  1275.         } else {
  1276.             if {![htmlIsThereAHomePage] ||
  1277.             [catch {htmlWhichHomePage "update"} hp]} {return}
  1278.             set folder [lindex $hp 0]
  1279.             set inclFldr [htmlWhichInclFolder "${folder}:"]
  1280.             set files [htmlAllHTMLfiles $folder]
  1281.         }
  1282.         set fid0 [open $files]
  1283.         while {![eof $fid0]} {
  1284.             gets $fid0 f
  1285.             if {$f == "" || [catch {open $f} fid]} {continue}
  1286.             message "Updating [file tail $f]…"
  1287.             getFileInfo $f finfo
  1288.             set created $finfo(created)
  1289.             set filecont [read $fid 16384]
  1290.             set limit [expr [eof $fid] ? 0 : 300]
  1291.             regsub -all "\n\r" $filecont "\r" filecont
  1292.             if {[regexp {\n} $filecont]} {
  1293.                 set newln "\n"
  1294.             } else {
  1295.                 set newln "\r"
  1296.             }
  1297.             set linenum 1
  1298.             set ismod 0
  1299.             set errf [string range $f [expr [string length $folder] + 1] end]
  1300.             set temp [htmlOpenAfile]
  1301.             set tmpfid [lindex $temp 0]
  1302.             set opening 0
  1303.             while {1} {
  1304.                 while {$opening || ([regexp -nocase -indices $sexpr $filecont res] && 
  1305.                 [expr [string length $filecont] - [lindex $res 0]] > $limit)} {
  1306.                     if {!$opening} {
  1307.                         incr linenum [regsub -all $newln [string range $filecont 0 [lindex $res 0]] {} dummy]
  1308.                         set l [expr 20 - [string length [file tail $f]]]
  1309.                         set ln [expr 5 - [string length $linenum]]
  1310.                         puts -nonewline $tmpfid [string range $filecont 0 [lindex $res 1]]
  1311.                         set readName [string range $filecont [lindex $res 0] [lindex $res 1]]
  1312.                         set filecont [string range $filecont [expr [lindex $res 1] + 1] end]
  1313.                     }
  1314.                     if {![regexp -nocase -indices $eexpr $filecont res1] ||
  1315.                     [expr [string length $filecont] - [lindex $res1 0]] <= $limit} {
  1316.                         if {[eof $fid]} {
  1317.                             append err [htmlBrwsErr $errf $l $linenum $ln "Opening include tag without a matching end tag." $f]
  1318.                         } else {
  1319.                             set opening 1
  1320.                         }
  1321.                         break
  1322.                     }
  1323.                     set toReplace [string trim [string range $filecont 0 [expr [lindex $res1 0] - 1]]]
  1324.                     set opening 0
  1325.                     if {[regexp -nocase -indices $sexpr $filecont res2]
  1326.                     && [lindex $res2 0] < [lindex $res1 0]} {
  1327.                         append err [htmlBrwsErr $errf $l $linenum $ln "Nested include tags." $f]
  1328.                         puts -nonewline $tmpfid [string range $filecont 0 [lindex $res1 1]]
  1329.                         incr linenum [regsub -all $newln [string range $filecont 0 [lindex $res1 1]] {} dummy]
  1330.                         set filecont [string range $filecont [expr [lindex $res1 1] + 1] end]
  1331.                         continue
  1332.                     }
  1333.                     if {[catch {htmlReadInclude $readName 0 $inclFldr} text]} {
  1334.                         append err [htmlBrwsErr $errf $l $linenum $ln $text $f]
  1335.                         puts -nonewline $tmpfid [string range $filecont 0 [lindex $res1 1]]                    
  1336.                         incr linenum [regsub -all $newln [string range $filecont 0 [lindex $res1 1]] {} dummy]
  1337.                         set filecont [string range $filecont [expr [lindex $res1 1] + 1] end]
  1338.                         continue
  1339.                     }
  1340.                     lappend modified $f
  1341.                     if {[string trim $text] != $toReplace} {
  1342.                         set ismod 1
  1343.                     }
  1344.                     puts -nonewline $tmpfid "$newln$newln$text$newln$newln"
  1345.                     puts -nonewline $tmpfid [string range $filecont [lindex $res1 0] [lindex $res1 1]]
  1346.                     incr linenum [regsub -all $newln [string range $filecont 0 [lindex $res1 1]] {} dummy]
  1347.                     set filecont [string range $filecont [expr [lindex $res1 1] + 1] end]
  1348.                 }
  1349.                 if {![eof $fid]} {
  1350.                     if {$opening} {
  1351.                         append filecont [read $fid 16384]
  1352.                     } else {
  1353.                         puts -nonewline $tmpfid [string range $filecont 0 [expr [string length $filecont] - 301]]
  1354.                         incr linenum [regsub -all $newln [string range $filecont 0 [expr [string length $filecont] - 301]] {} dummy]
  1355.                         set filecont "[string range $filecont [expr [string length $filecont] - 300] end][read $fid 16384]"
  1356.                     }
  1357.                     set limit [expr [eof $fid] ? 0 : 300] 
  1358.                 } else {
  1359.                     break
  1360.                 }                    
  1361.             }
  1362.             close $fid
  1363.             if {$ismod} {puts -nonewline $tmpfid $filecont}
  1364.             close $tmpfid
  1365.             if {$ismod} {
  1366.                 set linenum 1
  1367.                 set opening 0
  1368.                 set done 0
  1369.                 set fid [open [set temp1 [lindex $temp 1]]]
  1370.                 set filecont [read $fid 16384]
  1371.                 set limit [expr [eof $fid] ? 0 : 300]
  1372.                 set temp [htmlOpenAfile]
  1373.                 set tmpfid [lindex $temp 0]
  1374.                 while {1} {
  1375.                     if {$opening || ([regexp -nocase -indices {<!--[ \t\r\n]+#LASTMODIFIED[ \t\r\n]+[^>]+>} $filecont res] &&
  1376.                     [expr [string length $filecont] - [lindex $res 0]] > $limit)} {
  1377.                         if {!$opening} {
  1378.                             incr linenum [regsub -all "\n" [string range $filecont 0 [lindex $res 0]] {} dummy]
  1379.                             set l [expr 20 - [string length [file tail $f]]]
  1380.                             set ln [expr 5 - [string length $linenum]]
  1381.                             puts -nonewline $tmpfid [string range $filecont 0 [lindex $res 1]]
  1382.                             set lastMod [string range $filecont [lindex $res 0] [lindex $res 1]]
  1383.                             set filecont [string range $filecont [expr [lindex $res 1] + 1] end]
  1384.                         }
  1385.                         if {![regexp -nocase -indices {<!--[ \t\r\n]+/#LASTMODIFIED[ \t\r\n]+[^>]+>} $filecont res1] ||
  1386.                         [expr [string length $filecont] - [lindex $res1 0]] <= $limit} {
  1387.                             if {[eof $fid]} {
  1388.                                 append err [htmlBrwsErr $errf $l $linenum $ln "Opening 'last modified' tag without a matching closing tag." $f]
  1389.                             } else {
  1390.                                 set opening 1
  1391.                             }
  1392.                         } else {
  1393.                             set str [htmlGetLastMod $lastMod]
  1394.                             set done 1
  1395.                             if {$str == "0"} {
  1396.                                 append err [htmlBrwsErr $errf $l $linenum $ln "Invalid 'last modified' tags." $f]
  1397.                             } else {
  1398.                                 puts -nonewline $tmpfid "\r$str\r[string range $filecont [lindex $res1 0] end]"
  1399.                                 set filecont ""
  1400.                             }
  1401.                         }
  1402.                     }
  1403.                     if {![eof $fid] && !$done} {
  1404.                         if {$opening} {
  1405.                             append filecont [read $fid 16384]
  1406.                         } else {
  1407.                             puts -nonewline $tmpfid [string range $filecont 0 [expr [string length $filecont] - 301]]
  1408.                             incr linenum [regsub -all "\n" [string range $filecont 0 [expr [string length $filecont] - 301]] {} dummy]
  1409.                             set filecont "[string range $filecont [expr [string length $filecont] - 300] end][read $fid 16384]"
  1410.                         }
  1411.                         set limit [expr [eof $fid] ? 0 : 300] 
  1412.                     } else {
  1413.                         break
  1414.                     }
  1415.                 }
  1416.                 puts -nonewline $tmpfid $filecont
  1417.                 while {![eof $fid]} {
  1418.                     puts -nonewline $tmpfid [read $fid 16384]
  1419.                 }
  1420.                 close $fid
  1421.                 close $tmpfid
  1422.                 if {[catch {removeFile $f}] && [file exists $f]} {
  1423.                     append err "$errf[format "%$l\s" ""]; Could not write update to file. An error occurred.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t∞$f\r"
  1424.                 } else {
  1425.                     catch {copyFile [lindex $temp 1] $f; setFileInfo $f created $created}
  1426.                 }
  1427.                 catch {removeFile $temp1}
  1428.             }
  1429.             catch {removeFile [lindex $temp 1]}
  1430.         }
  1431.         close $fid0
  1432.         catch {removeFile $files}
  1433.     }
  1434.     if {[info exists err]} {
  1435.         new -n "* Errors *" -g $tileLeft $tileTop $tileWidth $errorHeight
  1436.         set name [lindex [winNames] 0]
  1437.         insertText "Errors:  (<uparrow> and <downarrow> to browse, <return> to go to file)\r\r"
  1438.         insertText $err
  1439.         htmlSetWin Brws
  1440.     } else {
  1441.         message "$where updated successfully."
  1442.     }
  1443.     if {[info exists modified]} {
  1444.         foreach w [winNames -f] {
  1445.             if {[lsearch -exact $modified [stripNameCount $w]] >= 0} {
  1446.                 if {[askyesno "Update affected windows?"] == "yes"} {
  1447.                     foreach ww [winNames -f] {
  1448.                         if {[lsearch -exact $modified [stripNameCount $ww]] >= 0} {
  1449.                             bringToFront $ww
  1450.                             revert
  1451.                         }
  1452.                     }
  1453.                 }
  1454.                 if {[info exists err]} {bringToFront $name}
  1455.                 return
  1456.             }
  1457.         }
  1458.     }
  1459. }
  1460.  
  1461. # Read content of a file to be included.
  1462. proc htmlReadInclude {incl nr fldr} {
  1463.     if {![regexp -nocase {file=\"([^\"]+)\"} $incl dum fil]} {
  1464.         error "Invalid opening include tag."
  1465.     }
  1466.     if {$fldr == "" && [regexp -nocase {^:INCLUDE:} $fil]} {error ":INCLUDE: doesn't map to a folder."}
  1467.     set fil [htmlResolveInclPath [htmlUnQuote $fil] $fldr]
  1468.     if {![file exists $fil]} {
  1469.         error "File not found."
  1470.     }
  1471.     if {[catch {readFile $fil} text]} {
  1472.         error "Could not read file."
  1473.     }
  1474.     regsub -all "\n\r" $text "\r" text
  1475.     if {$nr} {regsub -all "\n" $text "\r" text}
  1476.     # Remove include tags from inserted text
  1477.     regsub -all -nocase "<!--\[ \t\r\n\]+/?#INCLUDE\[ \t\r\n\]+\[^>\]+>" $text "" text
  1478.     return $text
  1479. }
  1480.